import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class IndexDbService {

  db: IDBDatabase;
  connect: IDBOpenDBRequest;
  constructor() {

  }

  /**
   * 数据库初始化
   * @param store_List string[]
   */
  initDB(store_List?: string[]) {
    const connect = window.indexedDB.open('DBName', 1);

    connect.onerror = (e) => {
      console.error('数据库连接失败');
      console.error(e);
    };

    connect.onsuccess = (e) => {
      console.log('数据库连接成功');
      console.log(e);

      // this.db = e.target['result'];
    };

    connect.onupgradeneeded = (e) => {
      console.log('onupgradeneeded.........');
      console.log(e);

      this.db = e.target['result'];
      const list = store_List ? ['defult', 'core', 'system', 'share', ...store_List] : ['defult', 'core', 'system', 'share'];
      this.creatStore(list);
    };

  }

  /**
   * 添加数据
   * @param store_name string
   * @param key string
   * @param data any 值为 undefined 时执行删除逻辑
   */
  setData(key: string, store_name?: string, data?: any) {
    if (data === undefined) {
      return this.remove(store_name, key);
    } else {
      return this.saveOrUpdate(store_name, key, data);
    }
  }
  /**
   * 查询数据
   * @param store_name string
   * @param key string
   */
  getData(key: string, store_name?: string) {
    if (key === undefined) {
      return this.selectAll(store_name);
    }
    return this.selectByKey(store_name, key);
  }

  /**
   * 清空对象仓库
   * @param store_name 值为 undefined 时，清空所有对象仓库
   */
  clearStore(store_name?: string) {
    if (store_name === undefined) {
      this.clearStoreAll();
    } else {
      this.clearStoreByName(store_name);
    }
  }

  /**
   * 删除指定数据库
   * @param DBName string
   */
  deleteDB(DBName: string) {
    return new Promise((resolve, reject) => {
      this.db.close();
      const delReq = window.indexedDB.deleteDatabase(DBName);
      delReq.onsuccess = (e) => {
        console.log(e);
        resolve();
      };
      delReq.onerror = (e) => {
        console.log(e);
        reject(e);
      };
      delReq.onblocked = (e) => {
        console.log(e);
        reject(e);
      };
    });
  }

  /**
   * 根据key查询数据
   * @param store_name string
   * @param key string
   */
  private selectByKey(store_name, key) {
    const store = this.getObjectStore(store_name, 'readonly');
    return new Promise((resolve, reject) => {
      store.get(key).onsuccess = (e) => {
        resolve(e.target['result'] || {});
      };
      store.get(key).onerror = (e) => {
        reject(e.target['error']);
      };
    });
  }

  /**
   * 查询整个对象仓库
   * @param store_name string
   */
  private selectAll(store_name) {
    const store = this.getObjectStore(store_name, 'readonly');
    return new Promise((resolve, reject) => {
      store.getAll().onsuccess = (e) => {
        resolve(e.target['result'] || []);
      };
      store.getAll().onerror = (e) => {
        reject(e.target['error']);
      };
    });
  }

  /**
   * 添加或修改数据
   * @param store_name string
   * @param key string
   * @param data any
   */
  private saveOrUpdate(store_name: string, key: string, data: any) {
    console.log('saveOrUpdate');
    return new Promise((resolve, reject) => {
      const store = this.getObjectStore(store_name, 'readwrite');
      let req;
      try {
        req = store.put(data, key);
        console.log(req);
      } catch (e) {
        throw (e);
      }
      req.onsuccess = (e) => {
        console.log('saveOrUpdate a success.....');
        resolve();
      };
      req.onerror = (e) => {
        console.log('saveOrUpdate a error.....');
        reject(e);
      };
    });
  }

  /**
   * 根据key删除对象仓库中的数据
   * @param store_name string
   * @param key string
   */
  private remove(store_name: string, key: string) {
    console.log('remove');
    return new Promise((resolve, reject) => {
      const store = this.getObjectStore(store_name, 'readwrite');
      const req = store.get(key);
      req.onsuccess = (e) => {
        const del_req = store.delete(key);
        del_req.onsuccess = (eve) => {
          console.log('remove a success.....');
          resolve();
        };
        del_req.onerror = (error) => {
          console.log('remove a error.....');
          reject(error);
        };
      };
      req.onerror = (e) => {
        reject(e);
      };
    });
  }

  /**
   * 清空所有对象仓库
   */
  private clearStoreAll() {
    const storeList = this.db.objectStoreNames || [];
    for (let i = 0; i < storeList.length; i++) {
      const element = storeList[i];
      this.clearStore(element);
    }
  }

  /**
   * 清空指定对象仓库
   * @param store_name string
   */
  private clearStoreByName(store_name: string) {
    const store = this.getObjectStore(store_name, 'readwrite');
    store.clear();
  }

  /**
   * 创建对象仓库
   */
  private creatStore(store_List) {
    if (store_List && store_List.length > 0) {
      for (let i = 0; i < store_List.length; i++) {
        const element = store_List[i];
        this.db.createObjectStore(element, { autoIncrement: true });
      }
    }
    console.log('creatStore.................');
  }

  /**
   * 删除对象仓库
   * @param store_name string | string[]
   */
  private deleteStore(store_name?: string | string[]) {
    if (store_name === undefined) {
      const storeList = this.db.objectStoreNames || [];
      for (let i = 0; i < storeList.length; i++) {
        const element = storeList[i];
        this.db.deleteObjectStore(element);
      }
    } else if (Array.isArray(store_name)) {
      for (let i = 0; i < store_name.length; i++) {
        const element = store_name[i];
        this.db.deleteObjectStore(element);
      }
    } else {
      this.db.deleteObjectStore(store_name);
    }
  }

  /**
   * 获取事务
   * @param store_name string
   * @param mode readonly | readwrite
   */
  private getObjectStore(store_name: string, mode: 'readonly' | 'readwrite') {
    return this.db.transaction(store_name, mode).objectStore(store_name);
  }
}
